"""
字符串的相似度计算
1. 按照单字符转为二进制数组，单字符串得出矩阵
2. 使用汉明距离实现获取差异值，得分范围0-1，1表示完全相同
*汉明距离*
    在信息论中，两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。
    换句话说，它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。
    举个例子：
        - 10010 和 10111 => 2 【挨个比较 遇到不同就+1】
"""
from decimal import Decimal, getcontext


def to_binary_matrix(input_var: str, bits: int = 8):
    """
    将输入内容转为二进制矩阵

    :param input_var: 输入的字符串
    :param bits: 每个字符使用的位数【默认为8位ASCII码】
    :return: 二维列表，表示二进制矩阵
    """
    binary_matrix = []
    for c in input_var:
        # 获取当前字符的Unicode编码
        code_point = ord(c)
        # 转二进制字符串，去掉'0b'前缀并填充到指定位数
        binary_str = bin(code_point)[2:].zfill(bits)
        # 转列表
        binary_arr = [int(bit) for bit in binary_str]
        # 加入矩阵
        binary_matrix.append(binary_arr)
    # 返回
    return binary_matrix


def compute_similarity(sample_data_matrix: [], input_data_matrix: [], suffix_cnt: int=8):
    """
    计算两个矩阵的相似度得分情况

    :param sample_data_matrix: 样本内容的矩阵数据
    :param input_data_matrix: 输入内容的矩阵数据
    :return: 浮点类型得分情况【0-1，1代表完全相同】
    """
    # 长度不同，以短一方的长度为截取参照
    # len_sample = len(sample_data_matrix)
    # len_input = len(input_data_matrix)
    # if len_sample != len_input:
    #     min_len = min(len_sample, len_input)
    #     sample_data_matrix = sample_data_matrix[:min_len]
    #     input_data_matrix = input_data_matrix[:min_len]

    # 计算总位数
    total_bits = len(sample_data_matrix) * len(sample_data_matrix[0]) if sample_data_matrix else 0

    # 无意义对比终止计算
    if total_bits == 0:
        return 1.0000 if sample_data_matrix == input_data_matrix else 0.0000

    # 计算距离
    distance = 0
    for sample_char, input_char in zip(sample_data_matrix, input_data_matrix):
        for sample_bit, input_bit in zip(sample_char, input_char):
            # 挨个比较 不同+1
            if sample_bit != input_bit:
                distance += 1

    # 计算相似度 = 1 - (距离 / 总位数)
    score_res = 1 - (distance / total_bits)

    # 使用 decimal 模块精确四舍五入到 suffix_cnt 位小数，并补零
    getcontext().rounding = "ROUND_HALF_UP"
    decimal_score = Decimal(str(score_res)).quantize(Decimal(f"0.{'0' * (suffix_cnt - 1)}1"))
    return float(decimal_score)


def get_sample_datas():
    """
    获取样本数据示例

    :return: 样本数据
    """
    str_arr = ['用户编码', '用户账号', '公司代码', '股票代码', '编码', '代码', '学生编号', '订单号']
    dict_res = {}
    for item in str_arr:
        dict_res[item] = to_binary_matrix(item)
    return dict_res


"""
测试
"""
dict_data = get_sample_datas()
print('读取样本示例：{}'.format(dict_data))


while True:
    input_content = input('请输入数据:')
    input_matrix = to_binary_matrix(input_content)
    for key in dict_data:
        sample_matrix = dict_data[key]
        score = compute_similarity(sample_matrix, input_matrix, 16)
        print('与 {} 比较，相似度得分等于：{}'.format(key, score))
